Quantification of Active Product Ingredient in a Pharmaceutical
Raman Spectroscopy Data and Multivariate Curve
Resolution with Alternating Least Squares (MCR-ALS)
Ricardo Cunha
cunha@iuta.de27 October, 2024
Source:vignettes/articles/demo_paracetamol_quantification_mcrals.Rmd
demo_paracetamol_quantification_mcrals.RmdThis article demonstrates how StreamFind can be used to quantity the active product ingredient (API) in Fizamol (i.e., paracetamol) from Raman data and using the Multivariate Curve Resolution with Alternating Least Squares (MCR-ALS) statistical method. A calibration curve is acquired with pure paracetamol diluted in water at different concentrations. Two Fizamol tablets (fiz_a and fiz_b) are diluted in water to a concentration of approx. 10 mg/ml and pure paracetamol (par) at 10 mg/ml are measured for quantification. Water is used as a blank.
# Creates the engine for Raman data
raman <- RamanEngine$new(analyses = raman_files)
# Modifies the replicate names
raman$analyses$replicates <- c(
rep("blank", 9),
rep("fiz_a", 9),
rep("fiz_b", 9),
rep("par", 3),
rep("cali_150_mgml", 9),
rep("cali_010_mgml", 9),
rep("cali_025_mgml", 9),
rep("cali_050_mgml", 9),
rep("cali_075_mgml", 9)
)
# Modifies the blank names
raman$analyses$blanks <- c(rep("blank", length(raman$analyses)))| analysis | replicate | blank | concentration |
|---|---|---|---|
| 240411_blank_200mW_OD3_2s_36n_pos1_r1 | blank | blank | 0.0 |
| 240411_blank_200mW_OD3_2s_36n_pos1_r2 | blank | blank | 0.0 |
| 240411_blank_200mW_OD3_2s_36n_pos1_r3 | blank | blank | 0.0 |
| 240411_blank_200mW_OD3_2s_36n_pos2_r1 | blank | blank | 0.0 |
| 240411_blank_200mW_OD3_2s_36n_pos2_r2 | blank | blank | 0.0 |
| 240411_blank_200mW_OD3_2s_36n_pos2_r3 | blank | blank | 0.0 |
| 240411_blank_200mW_OD3_2s_36n_pos3_r1 | blank | blank | 0.0 |
| 240411_blank_200mW_OD3_2s_36n_pos3_r2 | blank | blank | 0.0 |
| 240411_blank_200mW_OD3_2s_36n_pos3_r3 | blank | blank | 0.0 |
| 240412_Paracetamol-1mgmL_200mW_OD3_2s_36n_pos1_r1 | cali_010_mgml | blank | 1.0 |
| 240412_Paracetamol-1mgmL_200mW_OD3_2s_36n_pos1_r2 | cali_010_mgml | blank | 1.0 |
| 240412_Paracetamol-1mgmL_200mW_OD3_2s_36n_pos1_r3 | cali_010_mgml | blank | 1.0 |
| 240412_Paracetamol-1mgmL_200mW_OD3_2s_36n_pos2_r1 | cali_010_mgml | blank | 1.0 |
| 240412_Paracetamol-1mgmL_200mW_OD3_2s_36n_pos2_r2 | cali_010_mgml | blank | 1.0 |
| 240412_Paracetamol-1mgmL_200mW_OD3_2s_36n_pos2_r3 | cali_010_mgml | blank | 1.0 |
| 240412_Paracetamol-1mgmL_200mW_OD3_2s_36n_pos3_r1 | cali_010_mgml | blank | 1.0 |
| 240412_Paracetamol-1mgmL_200mW_OD3_2s_36n_pos3_r2 | cali_010_mgml | blank | 1.0 |
| 240412_Paracetamol-1mgmL_200mW_OD3_2s_36n_pos3_r3 | cali_010_mgml | blank | 1.0 |
| 240412_Paracetamol-2.5mgmL_200mW_OD3_2s_36n_pos1_r1 | cali_025_mgml | blank | 2.5 |
| 240412_Paracetamol-2.5mgmL_200mW_OD3_2s_36n_pos1_r2 | cali_025_mgml | blank | 2.5 |
| 240412_Paracetamol-2.5mgmL_200mW_OD3_2s_36n_pos1_r3 | cali_025_mgml | blank | 2.5 |
| 240412_Paracetamol-2.5mgmL_200mW_OD3_2s_36n_pos2_r1 | cali_025_mgml | blank | 2.5 |
| 240412_Paracetamol-2.5mgmL_200mW_OD3_2s_36n_pos2_r2 | cali_025_mgml | blank | 2.5 |
| 240412_Paracetamol-2.5mgmL_200mW_OD3_2s_36n_pos2_r3 | cali_025_mgml | blank | 2.5 |
| 240412_Paracetamol-2.5mgmL_200mW_OD3_2s_36n_pos3_r1 | cali_025_mgml | blank | 2.5 |
| 240412_Paracetamol-2.5mgmL_200mW_OD3_2s_36n_pos3_r2 | cali_025_mgml | blank | 2.5 |
| 240412_Paracetamol-2.5mgmL_200mW_OD3_2s_36n_pos3_r3 | cali_025_mgml | blank | 2.5 |
| 240412_Paracetamol-5mgmL_200mW_OD3_2s_36n_pos1_r1 | cali_050_mgml | blank | 5.0 |
| 240412_Paracetamol-5mgmL_200mW_OD3_2s_36n_pos1_r2 | cali_050_mgml | blank | 5.0 |
| 240412_Paracetamol-5mgmL_200mW_OD3_2s_36n_pos1_r3 | cali_050_mgml | blank | 5.0 |
| 240412_Paracetamol-5mgmL_200mW_OD3_2s_36n_pos2_r1 | cali_050_mgml | blank | 5.0 |
| 240412_Paracetamol-5mgmL_200mW_OD3_2s_36n_pos2_r2 | cali_050_mgml | blank | 5.0 |
| 240412_Paracetamol-5mgmL_200mW_OD3_2s_36n_pos2_r3 | cali_050_mgml | blank | 5.0 |
| 240412_Paracetamol-5mgmL_200mW_OD3_2s_36n_pos3_r1 | cali_050_mgml | blank | 5.0 |
| 240412_Paracetamol-5mgmL_200mW_OD3_2s_36n_pos3_r2 | cali_050_mgml | blank | 5.0 |
| 240412_Paracetamol-5mgmL_200mW_OD3_2s_36n_pos3_r3 | cali_050_mgml | blank | 5.0 |
| 240412_Paracetamol-7.5mgmL_200mW_OD3_2s_36n_pos1_r1 | cali_075_mgml | blank | 7.5 |
| 240412_Paracetamol-7.5mgmL_200mW_OD3_2s_36n_pos1_r2 | cali_075_mgml | blank | 7.5 |
| 240412_Paracetamol-7.5mgmL_200mW_OD3_2s_36n_pos1_r3 | cali_075_mgml | blank | 7.5 |
| 240412_Paracetamol-7.5mgmL_200mW_OD3_2s_36n_pos2_r1 | cali_075_mgml | blank | 7.5 |
| 240412_Paracetamol-7.5mgmL_200mW_OD3_2s_36n_pos2_r2 | cali_075_mgml | blank | 7.5 |
| 240412_Paracetamol-7.5mgmL_200mW_OD3_2s_36n_pos2_r3 | cali_075_mgml | blank | 7.5 |
| 240412_Paracetamol-7.5mgmL_200mW_OD3_2s_36n_pos3_r1 | cali_075_mgml | blank | 7.5 |
| 240412_Paracetamol-7.5mgmL_200mW_OD3_2s_36n_pos3_r2 | cali_075_mgml | blank | 7.5 |
| 240412_Paracetamol-7.5mgmL_200mW_OD3_2s_36n_pos3_r3 | cali_075_mgml | blank | 7.5 |
| 240412_Paracetamol-15mgmL_200mW_OD3_2s_36n_pos1_r1 | cali_150_mgml | blank | 15.0 |
| 240412_Paracetamol-15mgmL_200mW_OD3_2s_36n_pos1_r2 | cali_150_mgml | blank | 15.0 |
| 240412_Paracetamol-15mgmL_200mW_OD3_2s_36n_pos1_r3 | cali_150_mgml | blank | 15.0 |
| 240412_Paracetamol-15mgmL_200mW_OD3_2s_36n_pos2_r1 | cali_150_mgml | blank | 15.0 |
| 240412_Paracetamol-15mgmL_200mW_OD3_2s_36n_pos2_r2 | cali_150_mgml | blank | 15.0 |
| 240412_Paracetamol-15mgmL_200mW_OD3_2s_36n_pos2_r3 | cali_150_mgml | blank | 15.0 |
| 240412_Paracetamol-15mgmL_200mW_OD3_2s_36n_pos3_r1 | cali_150_mgml | blank | 15.0 |
| 240412_Paracetamol-15mgmL_200mW_OD3_2s_36n_pos3_r2 | cali_150_mgml | blank | 15.0 |
| 240412_Paracetamol-15mgmL_200mW_OD3_2s_36n_pos3_r3 | cali_150_mgml | blank | 15.0 |
| 240411_Fizamol-11_200mW_OD3_2s_36n_pos1_r1 | fiz_a | blank | NA |
| 240411_Fizamol-11_200mW_OD3_2s_36n_pos1_r2 | fiz_a | blank | NA |
| 240411_Fizamol-11_200mW_OD3_2s_36n_pos1_r3 | fiz_a | blank | NA |
| 240411_Fizamol-11_200mW_OD3_2s_36n_pos2_r1 | fiz_a | blank | NA |
| 240411_Fizamol-11_200mW_OD3_2s_36n_pos2_r2 | fiz_a | blank | NA |
| 240411_Fizamol-11_200mW_OD3_2s_36n_pos2_r3 | fiz_a | blank | NA |
| 240411_Fizamol-11_200mW_OD3_2s_36n_pos3_r1 | fiz_a | blank | NA |
| 240411_Fizamol-11_200mW_OD3_2s_36n_pos3_r2 | fiz_a | blank | NA |
| 240411_Fizamol-11_200mW_OD3_2s_36n_pos3_r3 | fiz_a | blank | NA |
| 240411_Fizamol-12_200mW_OD3_2s_36n_pos1_r1 | fiz_b | blank | NA |
| 240411_Fizamol-12_200mW_OD3_2s_36n_pos1_r2 | fiz_b | blank | NA |
| 240411_Fizamol-12_200mW_OD3_2s_36n_pos1_r3 | fiz_b | blank | NA |
| 240411_Fizamol-12_200mW_OD3_2s_36n_pos2_r1 | fiz_b | blank | NA |
| 240411_Fizamol-12_200mW_OD3_2s_36n_pos2_r2 | fiz_b | blank | NA |
| 240411_Fizamol-12_200mW_OD3_2s_36n_pos2_r3 | fiz_b | blank | NA |
| 240411_Fizamol-12_200mW_OD3_2s_36n_pos3_r1 | fiz_b | blank | NA |
| 240411_Fizamol-12_200mW_OD3_2s_36n_pos3_r2 | fiz_b | blank | NA |
| 240411_Fizamol-12_200mW_OD3_2s_36n_pos3_r3 | fiz_b | blank | NA |
| 240412_Paracetamol-10mgmL_200mW_OD3_2s_36n_pos3_r1 | par | blank | NA |
| 240412_Paracetamol-10mgmL_200mW_OD3_2s_36n_pos3_r2 | par | blank | NA |
| 240412_Paracetamol-10mgmL_200mW_OD3_2s_36n_pos3_r3 | par | blank | NA |
raman$plot_spectra(colorBy = "replicates")Raw Raman spectra for each analysis replicate.
Pre-processing Raman Data
The data is pre-processed using a workflow that includes the following steps:
- Averaging the spectra for each analysis replicate.
- Subtracting the blank spectra.
- Smoothing the spectra using the Savitzky-Golay method.
- Deleting the spectra sections that are not relevant for the analysis.
- Correcting the spectra baseline using the Asymmetric Least Squares (airPLS) method.
The methods ca be applied one at the time or used to bluid a Workflow object that will apply all methods in sequence within engine, as shown below.
# Creates the workflow for Raman data
# with an ordered list of processing settings
raman_workflow <- StreamFind::Workflow(
list(
RamanSettings_AverageSpectra_StreamFind(),
RamanSettings_SubtractBlankSpectra_StreamFind(),
RamanSettings_SmoothSpectra_savgol(fl = 21, forder = 4, dorder = 0),
RamanSettings_DeleteSpectraSection_StreamFind(shiftmin = -100, shiftmax = 350),
RamanSettings_DeleteSpectraSection_StreamFind(shiftmin = 1800, shiftmax = 2500),
RamanSettings_CorrectSpectraBaseline_airpls(lambda = 45, differences = 1, itermax = 30)
)
)
show(raman_workflow)
Workflow
1: AverageSpectra (StreamFind)
2: SubtractBlankSpectra (StreamFind)
3: SmoothSpectra (savgol)
4: DeleteSpectraSection (StreamFind)
5: DeleteSpectraSection (StreamFind)
6: CorrectSpectraBaseline (airpls)
# Adds the workflow to the engine
raman$workflow <- raman_workflow
# Runs the workflow
raman$run_workflow()
raman$plot_spectra()Pre-processed Raman spectra for analysis replicate.
Applying MCR-ALS for Quantification
The quantification of paracetamol from the pre-processed Raman spectra is performed using the Multivariate Curve Resolution (MCR) with Alternating Least Squares (ALS) method via integration of the mdatools R package.
# Gets a matrix with spectra from the Raman engine
raman_matrix <- raman$get_spectra_matrix()
str(raman_matrix) num [1:8, 1:574] 221 304 384 714 183 ...
- attr(*, "dimnames")=List of 2
..$ : chr [1:8] "fiz_a" "fiz_b" "par" "cali_150_mgml" ...
..$ : chr [1:574] "350.35779" "353.3808" "356.40076" "359.41766" ...
- attr(*, "xValues")= num [1:574] 350 353 356 359 362 ...
# Creates the statistic engine for the statistic analysis
stat <- StatisticEngine$new(analyses = raman_matrix)
stat
StatisticEngine
name NA
date 2024-10-27 13:04:44.891242
file NA
Workflow empty
StreamFind::StatisticAnalyses
analysis type features
1: cali_010_mgml model 574
2: cali_025_mgml model 574
3: cali_050_mgml model 574
4: cali_075_mgml model 574
5: cali_150_mgml model 574
6: fiz_a model 574
7: fiz_b model 574
8: par model 574
Results empty
# Applies the MCR-ALS method with the run method of the engine
stat$run(StatisticSettings_MakeModel_mcrals_mdatools(ncomp = 2))
plot(stat$model)Overview plot for the MCR-ALS model
# Applies the quantification method with the run method of the engine
# Concentrations with NA for unknown values
stat$run(
StatisticSettings_Quantify_mcrals(
concentrations = c(1, 2.5, 5.0, 7.5, 15.0, NA_real_, NA_real_, NA_real_)
)
)The MCR-ALS was applied with two components and the quantification results are shown below. The component with the highest combined explained variance and R2 values for the calibration curve should be used for quantification. The analysis par should have about 10 in mg/ml of paracetamol while the analyses fiz_a and fiz_b should a little less than 10 mg/ml due to presence of formulation ingredients and possible loss of API during sample preparation.
# Gets the quantification results
stat$quantification@quantities$`Comp 1`
result analysis intensity concentration rsquared exp_variance
<char> <char> <num> <num> <num> <num>
1: model cali_010_mgml 1.74826 1.00000 0.8204218 26.5
2: model cali_025_mgml 0.00000 2.50000 0.8204218 26.5
3: model cali_050_mgml 0.00000 5.00000 0.8204218 26.5
4: model cali_075_mgml 5.15870 7.50000 0.8204218 26.5
5: model cali_150_mgml 97.78008 15.00000 0.8204218 26.5
6: model fiz_a 2574.24296 302.32359 0.8204218 26.5
7: model fiz_b 2560.22155 300.69743 0.8204218 26.5
8: model par 83.92187 13.50472 0.8204218 26.5
$`Comp 2`
result analysis intensity concentration rsquared exp_variance
<char> <char> <num> <num> <num> <num>
1: model cali_010_mgml 113.9242 1.000000 0.9980675 73.3
2: model cali_025_mgml 278.4266 2.500000 0.9980675 73.3
3: model cali_050_mgml 615.1774 5.000000 0.9980675 73.3
4: model cali_075_mgml 944.3979 7.500000 0.9980675 73.3
5: model cali_150_mgml 2068.4674 15.000000 0.9980675 73.3
6: model fiz_a 914.8382 6.985566 0.9980675 73.3
7: model fiz_b 914.1857 6.980938 0.9980675 73.3
8: model par 1279.5648 9.572403 0.9980675 73.3